﻿namespace DeltaGroup.WheelOfJeopardy.UI.Screens
{
    using System;
    using System.Timers;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;

    using DeltaGroup.WheelOfJeopardy.UI.Events;
    using DeltaGroup.WheelOfJeopardy.UI.ViewModel;

    /// <summary>
    ///     Interaction logic for ChallengePrompt.xaml
    /// </summary>
    public partial class ChallengePrompt : UserControl
    {
        #region Fields

        private const double TICK_INTERVAL = 1000;

        private Timer _timer;

        #endregion Fields

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="ChallengePrompt"/> class.
        /// </summary>
        public ChallengePrompt()
        {
            InitializeComponent();
        }

        #endregion Constructors

        #region Events

        /// <summary>
        /// Occurs when [response received].
        /// </summary>
        public event EventHandler<ResponseReceivedEventArgs> ResponseReceived;

        /// <summary>
        /// Occurs when [response timer expired].
        /// </summary>
        public event EventHandler ResponseTimerExpired;

        #endregion Events

        #region Properties

        /// <summary>
        /// Gets or sets the seconds left.
        /// </summary>
        /// <value>The seconds left.</value>
        private int SecondsLeft
        {
            get { return (DataContext as ChallengePromptViewModel).TimeRemaining; }
            set { (DataContext as ChallengePromptViewModel).TimeRemaining = value; }
        }

        #endregion Properties

        #region Methods

        /// <summary>
        /// Starts the timer.
        /// </summary>
        public void StartTimer()
        {
            _timer = new Timer(SecondsLeft*TICK_INTERVAL);
            _timer.Interval = TICK_INTERVAL;
            _timer.AutoReset = true;
            _timer.Elapsed += TimeRemaining_Elapsed;
            _timer.Start();
        }

        /// <summary>
        /// Determines whether this instance can respond the specified sender.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Input.CanExecuteRoutedEventArgs"/> instance containing the event data.</param>
        private void CanRespond(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = Validation.GetHasError(ChallengeResponse) == false;
            e.Handled = true;
        }

        /// <summary>
        /// Raises the no response received.
        /// </summary>
        private void RaiseNoResponseReceived()
        {
            if (ResponseTimerExpired != null)
                ResponseTimerExpired(this, EventArgs.Empty);
        }

        /// <summary>
        /// Raises the response received.
        /// </summary>
        /// <param name="response">The response.</param>
        private void RaiseResponseReceived(string response)
        {
            if (ResponseReceived != null)
                ResponseReceived(this, new ResponseReceivedEventArgs(response));
        }

        /// <summary>
        /// Respondeds the specified sender.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.Input.ExecutedRoutedEventArgs"/> instance containing the event data.</param>
        private void Responded(object sender, ExecutedRoutedEventArgs e)
        {
            _timer.Dispose();
            RaiseResponseReceived(ChallengeResponse.Text);
        }

        /// <summary>
        /// Handles the Elapsed event of the TimeRemaining control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Timers.ElapsedEventArgs"/> instance containing the event data.</param>
        private void TimeRemaining_Elapsed(object sender, ElapsedEventArgs e)
        {
            Dispatcher.Invoke(
                new Action(() =>
                               {
                                   SecondsLeft -= 1;

                                   if (SecondsLeft == 0)
                                   {
                                       _timer.Dispose();

                                       ResponseSection.Visibility = Visibility.Hidden;
                                       TimeExpiredSection.Visibility = Visibility.Visible;
                                   }
                               }
                    ));
        }

        /// <summary>
        /// Timers the expire.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void TimerExpire(object sender, RoutedEventArgs e)
        {
            RaiseNoResponseReceived();
        }

        #endregion Methods
    }
}